#include "widget.h"
#include "localdb.h"
#include "ui_widget.h"
#include <QHostInfo>
#include <QFileInfo>
#include <QFileDialog>
#include <QFile>
#include <QTime>
#include <QTimer>
#include <QMessageBox>
#include <QThread>


//-------------------------------------------------------------------------------------



Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);
    //get local ip
    QString hostName = QHostInfo::localHostName();
    QHostInfo hostInfo = QHostInfo::fromName(hostName);
    QList<QHostAddress> addrlist = hostInfo.addresses();
    for(int i=0;i<addrlist.count();i++)
    {
        QHostAddress host = addrlist.at(i);
        if(QAbstractSocket::IPv4Protocol == host.protocol())
        {
            QString ip = host.toString();
            ui->uiip->addItem(ip);
        }
    }
    m_socket = new SerSocket(this);

    //sign up
    connect(m_socket,&SerSocket::stateChanged,this,&Widget::on_statechange);
    connect(this,&Widget::ConnectToServer,m_socket,&SerSocket::ClientConnectToHost);
    connect(this,&Widget::Online,m_socket,&SerSocket::ClientSendingText);
    connect(this,&Widget::heart_jump,m_socket,&SerSocket::Jump);

    connect(m_socket,&SerSocket::SignalUID,this,[&](const QString& uid){
        use_uid = uid;
        sign_info->insert("UID",uid);
    });
    connect(m_socket,&SerSocket::Updatefinish,this,[&](){ update_finish = true;});
    connect(m_socket,&SerSocket::FileSucccess,this,[&](){ notsend = false;});

    connect(m_socket,&SerSocket::connected,this,&Widget::on_connected);
    connect(m_socket,&SerSocket::disconnected,this,&Widget::on_disconnected);

    //load list
    connect(m_socket,&SerSocket::ServerSendList,this,&Widget::getList);
    connect(m_socket,&SerSocket::ServerSendUpdateList,this,&Widget::getUpdateList);

    //receive message
    connect(m_socket,&SerSocket::ServerSendUnreadMsg,this,&Widget::getUpdateMessage);
    connect(m_socket,&SerSocket::ServerSendUnreadFile,this,&Widget::getUpdateFileLists);
    //connect(this,&Widget::ClientRcvPath,m_socket,&SerSocket::ClientSendingFRequese);

//    connect(m_socket,&SerSocket::SignalRcvPrepare,this,&Widget::getRcvPath);
//    connect(m_socket,&SerSocket::ServerFileinfo,this,[&](const QString& finfo,const QString& fid){
//        QJsonObject frd = id_list->value(fid).toObject();
//        QString name = frd.value("name").toString();
//        ui->history->appendPlainText(name+"[in]"+finfo);});
//    connect(this,&Widget::ClientRcvPath,m_socket,&SerSocket::ClientSendingRPath);

    connect(m_socket,&SerSocket::Signal,this,[&](const QString& data){
        ui->history->appendPlainText(data);
    });

    //sent message
    //connect(this,&Widget::heart_jump,&Widget::senttext);
    //connect(this,&Widget::heart_jump,this,&Widget::sentfile);

    connect(this,&Widget::Text,m_socket,&SerSocket::ClientSendingText);
    connect(m_socket,&SerSocket::GetMsgId,this,&Widget::update_msgid);
    connect(this,&Widget::FilePath,m_socket,&SerSocket::ClientSendingFile);

    Clock = new QTimer;
    connect(Clock,&QTimer::timeout,this,&Widget::up_date);
    Clock->start(2000);
}

Widget::~Widget()
{
    delete ui;
    delete m_socket;
    delete id_list;
    delete Clock;
}

void Widget::on_btnconnect_clicked()
{
    m_socket->ClientConnectToHost("101.43.221.29",8888);
}

void Widget::on_btnsign_clicked()
{
    use_uid = ui->uiid->text();
    QString pswd = ui->uipswd->text();
    ui->uipswd->clear();
    use_ip = ui->uiip->currentText();
    sign_info = new QJsonObject;
    sign_info->insert("UID",use_uid);
    sign_info->insert("password",pswd);
    sign_info->insert("ip",use_ip);
    QJsonDocument jsonDocument;
    jsonDocument.setObject(*sign_info);
    emit Online(jsonDocument.toJson(),0x05);
    onsign = true;
}

void Widget::on_btnlog_clicked()
{
    use_name = ui->uiname->text();
    QString pswd = ui->uipswd->text();
    ui->uipswd->clear();
    use_ip = ui->uiip->currentText();
    sign_info = new QJsonObject;
    sign_info->insert("password",pswd);
    sign_info->insert("name",use_name);
    QJsonDocument jsonDocument;
    jsonDocument.setObject(*sign_info);
    emit Online(jsonDocument.toJson(),0x04);
}

void Widget::on_btnstop_clicked()
{
    online = false;
    m_socket->disconnectFromHost();
    use_ip.clear();
    use_uid.clear();
    use_name.clear();
}

void Widget::up_date()
{
    //   if((jump+1)%2==0)
    //   {
    /*if(!online)
            m_socket->ClientConnectToHost("101.43.221.29",8888);  */
    if(m_socket->IsOnline())
    {
        QJsonObject uid_bag;
        uid_bag.insert("UID",use_uid);
        uid_bag.insert("last_message_id",QString::number(db.GetMaxMessageId()));
        uid_bag.insert("last_user","1");
        uid_bag.insert("last_group_id","1");
        QJsonDocument jsonDocument;
        jsonDocument.setObject(uid_bag);
//        update_finish = false;
//        if(!file_que.isEmpty())
//            sfile_finish = false;
//        if(!msg_que.isEmpty())
//            smsg_finish = false;
        emit heart_jump(jsonDocument.toJson());}
    //    else
    //    {
    //        /*if(onsign) //用户是已经登录的状态（记住密码）
    //            {
    //                QJsonDocument jsonDocument;
    //                jsonDocument.setObject(*sign_info);
    //                emit Online(jsonDocument.toJson(),0x05);}
    //            else
    //            {*/
    //        ui->uistatus->setText("请连接后登录");
    //    }
}
/*else
   {
       if(sfile_finish && update_finish && smsg_finish)
             m_socket->disconnectFromHost();
   }*/

//列表修改
void Widget::getList(const QJsonArray& list,const QJsonArray& glist)
{
    db.Connect(use_uid);
    int frdnum = list.size();
    id_list = new QJsonObject();
    name_list = new QJsonObject();
    ui->cbox_fd->clear();
    for (int i =0; i < frdnum; i++)
    {
        QJsonObject member = list.at(i).toObject();
        QString name = member.value("name").toString()+"*"+member.value("uid").toString();
        ui->cbox_fd->addItem(name);
        QJsonObject data;
        data.insert("ip",member.value("ip").toString());
        data.insert("name",member.value("name").toString());
        db.AddFriend(member.value("uid").toInt(),member.value("name").toString(),member.value("ip").toString(),member.value("job").toString());
        id_list->insert(member.value("uid").toString(),data);
        data.insert("uid",member.value("uid").toString());
        name_list->insert(name,data);}
    int gnum = glist.size();
    group_list = new QJsonObject();
    //ui->cbox_group->clear();
    for (int i =0; i < gnum; i++)
    {
        QJsonObject member = glist.at(i).toObject();
        //ui->cbox_frd->addItem(name);
        QJsonObject data;
        data.insert("category",member.value("category").toString());
        data.insert("name",member.value("name").toString());
        db.AddGroup(member.value("uid").toInt(),member.value("name").toString(),member.value("memberList").toString(),member.value("category").toString());
        group_list->insert(member.value("uid").toString(),data);
    }
}

void Widget::getUpdateList(const QJsonArray &l_data,const QJsonArray &g_data)
{
    int frdnum = l_data.size();
    for (int i =0; i < frdnum; i++)
    {
        QJsonObject member = l_data.at(i).toObject();
        QString fid = member.value("UID").toString();
        QJsonObject m_data = member.value("data").toObject();
        if (member.value("operate").toString() == "add")
        {
            QJsonObject data;
            data.insert("ip",m_data.value("ip").toString());
            data.insert("name",m_data.value("name").toString());
            id_list->insert(fid,data);
            data.insert("uid",fid);
            db.AddFriend(member.value("uid").toInt(),member.value("name").toString(),member.value("ip").toString(),member.value("job").toString());
            name_list->insert(m_data.value("name").toString()+"*"+fid,data);
            ui->cbox_fd->addItem(m_data.value("name").toString()+"*"+fid,data);}
        else
        {
            QJsonObject data = id_list->value(fid).toObject();
            data.remove("ip");
            data.insert("ip",m_data.value("ip"));
        }
    }
    int gnum = g_data.size();
    for (int i =0; i < gnum; i++)
    {
        QJsonObject member = g_data.at(i).toObject();
        QString fid = member.value("id").toString();
        QJsonObject m_data = member.value("data").toObject();
        if (member.value("operate").toString() == "add")
        {
            QJsonObject data;
            data.insert("category",member.value("category").toString());
            data.insert("name",member.value("name").toString());
            db.AddGroup(member.value("uid").toInt(),member.value("name").toString(),member.value("memberList").toString(),member.value("category").toString());
            group_list->insert(m_data.value("id").toString(),data);}
    }

}


//接收信息
void Widget::getUpdateMessage(const QJsonArray &msg_list)
{
    int num = msg_list.size();
    for (int i =0; i < num; i++)
    {
        QJsonObject Friend = msg_list.at(i).toObject();
        Message Msg;
        Msg.tid = Friend.value("TID").toString().toInt();
        Msg.rid = Friend.value("RID").toString().toInt();
        Msg.msg = Friend.value("content").toString();
        Msg.id = Friend.value("MID").toString().toInt();
        Msg.time = QDateTime::fromString(Friend.value("time").toString(), "yyyy-MM-dd hh:mm:ss");
        db.AddMessage(Msg);
        ui->history->appendPlainText(id_list->value(QString::number(Msg.tid)).toString()+"[in]"+Msg.msg);}
}

void Widget::getUpdateFileLists(const QJsonArray &fmsg_list)
{
    int num = fmsg_list.size();
    for (int i =0; i < num; i++)
    {
        QJsonObject Friend = fmsg_list.at(i).toObject();
        Message Msg;
        Msg.tid = Friend.value("TID").toString().toInt();
        Msg.rid = Friend.value("RID").toString().toInt();
        Msg.msg = Friend.value("content").toString();
        QString rfileName = Msg.msg.section("##",0,0);
        int rfileSize = Msg.msg.section("##",1,1).toInt();
        Msg.id = Friend.value("MID").toString().toInt();
        Msg.time = QDateTime::fromString(Friend.value("time").toString(), "yyyy-MM-dd hh:mm:ss");
        db.AddMessage(Msg);
        ui->filelist->addItem(tr("%1##%2").arg(rfileName).arg(QString::number(Msg.id)));
        ui->history->appendPlainText(id_list->value(QString::number(Msg.tid)).toString()+"[in]"+rfileName+" "+QString::number(rfileSize));}
}

//接收文件
void Widget::on_btngetfile_clicked(){
    QString file_info = ui->cbox_fd->currentText(); //*******
    QString fid = file_info.section("##",1,1);
    QString fname = file_info.section("##",0,0);
    QString dir = QFileDialog::getExistingDirectory(this,"选择文件夹 ","D:");
    emit ClientRcvPath(dir,fname,fid);
}

//void Widget::getRcvPath()
//{
//    QString dir = QFileDialog::getExistingDirectory(this,"选择文件夹 ","D:");
//    emit (dir);
//}

//Show status
void Widget::on_connected()
{
    online = true;
    ui->history->appendPlainText("JUMP->");
}

void Widget::on_disconnected()
{
    online = false;
    ui->history->appendPlainText("<-JUMP");
}

void Widget::on_statechange(QAbstractSocket::SocketState socketState)
{
    switch (socketState)
    {
    case QAbstractSocket::UnconnectedState:
        ui->uistatus->setText("UnconnectedState");break;
    case QAbstractSocket::HostLookupState:
        ui->uistatus->setText("HostLookupState");break;
    case QAbstractSocket::ConnectedState:
        ui->uistatus->setText("ConnectedState");break;
    case QAbstractSocket::ConnectingState:
        ui->uistatus->setText("ConnectingState");break;
    case QAbstractSocket::BoundState:
        ui->uistatus->setText("BoundState");break;
    case QAbstractSocket::ClosingState:
        ui->uistatus->setText("ClosingState");break;
    case QAbstractSocket::ListeningState:
        ui->uistatus->setText("ListeningState");break;
    }
}

//发送消息
void Widget::on_btntext_clicked()
{
    QString friend_name = ui->cbox_fd->currentText(); //####
    QJsonObject now_friend = name_list->value(friend_name).toObject();
    now_uid = now_friend.value("uid").toString();
    QJsonObject text_bag;
    text_bag.insert("UID",use_uid);
    text_bag.insert("RID",now_uid);
    text_bag.insert("content",ui->textEdit->toPlainText());
    QJsonDocument jsonDocument;
    jsonDocument.setObject(text_bag);
    QByteArray tbox = jsonDocument.toJson();
    emit Text(tbox,0x06);
    Message m_msg;
    m_msg.msg = ui->textEdit->toPlainText();
    m_msg.rid = use_uid.toInt();
    m_msg.tid = now_friend.value("uid").toInt();
    m_msg.time = QDateTime::currentDateTime();
    msg_que.enqueue(m_msg);
    now_msg =ui->textEdit->toPlainText();
    ui->history->appendPlainText(use_name+" [out] "+now_msg+"\n");
}

void Widget::update_msgid(const int& mid){
    Message m_msg = msg_que.dequeue();
    m_msg.id = mid;
    db.AddMessage(m_msg);
}

//void Widget::senttext()
//{
//    while(!msg_que.isEmpty()){
//        QByteArray mbag = msg_que.dequeue();
//        emit Text(mbag,0x06);
//    }
//    smsg_finish = true;
//}

void Widget::on_btnfile_clicked()
{
    QString friend_name = ui->cbox_fd->currentText(); //####
    QJsonObject now_friend = name_list->value(friend_name).toObject();
    now_uid = now_friend.value("id").toString();
    QJsonObject file_bag;
    file_bag.insert("UID",use_uid);
    file_bag.insert("RID",now_uid);
    QString filePath = QFileDialog::getOpenFileName(this,"open","../");
    QFileInfo info(filePath);
    QString fileName = info.fileName();
    int fileSize = info.size();
    QString head = tr("%1##%2").arg(fileName).arg(fileSize);
    file_bag.insert("content",head);
    QJsonDocument jsonDocument;
    jsonDocument.setObject(file_bag);
    file_box fbox;
    fbox.info = jsonDocument.toJson();
    fbox.fpath = filePath;
    fbox.sz = fileSize;
    file_que.enqueue(fbox);
    emit FilePath(fbox);
    Message m_msg;
    m_msg.msg = head;
    m_msg.rid = use_uid.toInt();
    m_msg.tid = now_friend.value("uid").toInt();
    m_msg.time = QDateTime::currentDateTime();
    msg_que.enqueue(m_msg);
    now_msg = filePath;
    ui->history->appendPlainText(use_name+" [out] "+now_msg+"\n");
}

//void Widget::sentfile()
//{
//    while(!file_que.isEmpty()){
//        if(!notsend)
//        {
//            file_box fileBox = file_que.dequeue();
//            notsend = true;
//            emit FilePath(fileBox);
//        }
//    }
//    sfile_finish = true;
//}

void Widget::on_btnclean_clicked()
{
    ui->history->clear();
}

